﻿using System.Web.UI.WebControls;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Globalization;
using System.Web;
using System.Threading;
using System.Data;
using System.Xml.Linq;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
using System.Security.Cryptography;


namespace CodeMatrix.Utilities
{

    public sealed class EnumUtility
    {

        private const string _displayTemplate = "_SysEnum_{0}_{1}";

        public static ListItemCollection GetListItemCollection(Type type)
        {
            ListItemCollection items = new ListItemCollection();
            string enumName = type.Name;
            foreach (MemberInfo i in type.GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                object objEnum = type.InvokeMember(i.Name, BindingFlags.GetField, null, type, null);
                object objDisplayName = HttpContext.GetGlobalResourceObject("Resource", string.Format(_displayTemplate, enumName, objEnum.ToString()), Thread.CurrentThread.CurrentCulture);

                if (objDisplayName == null)
                {
                    items.Add(new ListItem(objEnum.ToString(), objEnum.GetHashCode().ToString()));
                }
                else
                {
                    items.Add(new ListItem(objDisplayName.ToString(), objEnum.GetHashCode().ToString()));
                }
            }


            return items;
        }

        public static ListItemCollection GetListItemCollection<T>(Type type, params T[] defaultItems)
        {
            ListItemCollection items = EnumUtility.GetListItemCollection(type);
            foreach (ListItem i in items)
            {
                i.Selected = Array.Exists<T>
                                    (
                                        defaultItems,
                                        delegate(T iItem)
                                        {
                                            return iItem.ToString() == i.Value;
                                        }
                                    );
            }
            return items;
        }

        public static string GetDisplayName(Type enumType, object value)
        {
            object obj = HttpContext.GetGlobalResourceObject("Resource", string.Format(_displayTemplate, enumType.Name, value.ToString()), Thread.CurrentThread.CurrentCulture);
            return obj == null
                    ? Enum.GetName(enumType, value)
                    : obj.ToString();
        }

        public static string GetDisplayName<T>(T value) where T : struct
        {
            Type enumType = typeof(T);
            object obj = HttpContext.GetGlobalResourceObject("Resource", string.Format(_displayTemplate, enumType.Name, value.ToString()), Thread.CurrentThread.CurrentCulture);
            return obj == null
                    ? Enum.GetName(enumType, value)
                    : obj.ToString();
        }

        public static UInt32 SumSelected<T>(Type type, params T[] eValue)
        {
            List<T> values = new List<T>(eValue);
            UInt32 sum = default(UInt32);

            foreach (MemberInfo i in type.GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                object o = type.InvokeMember(i.Name, BindingFlags.GetField, null, type, null);
                values.Find(delegate(T x)
                {
                    uint iSum = Convert.ToUInt32(x);
                    if (o.GetHashCode() == iSum)
                    {
                        sum += iSum;
                    }
                    return false;
                });
            }

            return sum;
        }

        public static uint SumSelected(Type type, ListItemCollection lists)
        {
            List<string> lList = new List<string>();
            foreach (ListItem i in lists)
            {
                if (!string.IsNullOrEmpty(i.Value) && i.Selected)
                {
                    lList.Add(i.Value);
                }
            }
            return EnumUtility.SumSelected(type, lList.ToArray());
        }

        public static void SetSelected(UInt32 eValue, ListItemCollection lists)
        {
            foreach (ListItem i in lists)
            {
                if (!string.IsNullOrEmpty(i.Value))
                {
                    i.Selected = (eValue & UInt32.Parse(i.Value)) > 0;
                }
            }
        }

        public static void SetSelected<T>(T eValue, ListItemCollection lists) where T : struct
        {
            EnumUtility.SetSelected((UInt32)eValue.GetHashCode(), lists);
        }

    }

    public static class WebUiHelper
    {

        public static T[] GetSelectedCheckBox<T>(GridView gv,string dataKeyName, string checkBoxName)
        {
            List<T> cT = new List<T>();
            foreach (GridViewRow i in gv.Rows)
            {
                CheckBox iCb = i.FindControl(checkBoxName) as CheckBox;
                if (iCb.Checked)
                {
                    cT.Add((T)gv.DataKeys[i.RowIndex][dataKeyName]);
                }
            }
            return cT.ToArray();
        }

        public static T[] GetSelectedCheckBox<T>(ListView gv, string dataKeyName, string checkBoxName)
        {
            
            List<T> cT = new List<T>();
            foreach (var i in gv.Items)
            {
                CheckBox iCb = i.FindControl(checkBoxName) as CheckBox;
                if (iCb.Checked)
                {
                    cT.Add((T)gv.DataKeys[i.DisplayIndex][dataKeyName]);
                }
            }
            return cT.ToArray();
        }


    }

    public static class MembershipHelper
    {

        public static string GetEncodedPassword(string userName,string algoType)
        {

            SqlParameter pUserName = new SqlParameter("@UserName", userName);
            SqlParameter pPassword = new SqlParameter("@Password",SqlDbType.NVarChar,4000);
            SqlParameter pPasswordSalt = new SqlParameter("@PasswordSalt", SqlDbType.NVarChar, 4000);

            pPassword.Direction = ParameterDirection.Output;
            pPasswordSalt.Direction = ParameterDirection.Output;

            CodeHelper.ExecuteNonQuery(@"select @Password = m.[Password] , @PasswordSalt = m.PasswordSalt from aspnet_membership as m
join aspnet_users as u on m.UserId = u.UserId
where u.UserName = @UserName", new SqlParameter[]{
                                pUserName,
                                pPassword,
                                pPasswordSalt
                             });

            return EncodePassword(
                pPassword.Value.ToString(),
                pPasswordSalt.Value.ToString(),
                algoType);

        }

        public static string GetEncodedPassword(string userName)
        {
            return GetEncodedPassword(userName, "SHA1");
        }

        public static string EncodePassword(string pass, string salt,string algorithmType)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(pass);
            byte[] src = Encoding.Unicode.GetBytes(salt);
            byte[] dst = new byte[src.Length + bytes.Length];
            Buffer.BlockCopy(src, 0, dst, 0, src.Length);
            Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
            HashAlgorithm algorithm = HashAlgorithm.Create(algorithmType);
            byte[] inArray = algorithm.ComputeHash(dst);
            return Convert.ToBase64String(inArray);
        }

        public static string EncodePassword(string pass, string salt)
        {
            return EncodePassword(pass, salt, "SHA1");
        }

    }

    public static class CodeHelper
    {

        private static string _connectionString;

        public static XElement CreateXData<T>(IEnumerable<T> data, string type)
        {
            System.Xml.Linq.XElement xData = new System.Xml.Linq.XElement(XName.Get("data"));
            foreach (var i in data)
            {
                xData.Add(new XElement(type, i));
            }
            return xData;
        }

        public static string[] GetXData(XElement data)
        {
            List<string> cT = new List<string>();

            var cData = (from o in data.Descendants()
                         select o.Value);
            foreach (var i in cData)
            {
                cT.Add(i);
            }

            return cT.ToArray();
        }

        public static string StripHtml(string html, bool allowHarmlessTags)
        {
            if (html == null || html == string.Empty)
                return string.Empty;

            if (allowHarmlessTags)
                return System.Text.RegularExpressions.Regex.Replace(html, "", string.Empty);

            return System.Text.RegularExpressions.Regex.Replace(html, "<[^>]*>", string.Empty);
        }

        /// <summary>
        /// Retrieve menu
        /// *Should have following column
        /// *Id , *Title , *Url , Parent ,Desc
        /// </summary>
        /// <param name="tbl"></param>
        /// <returns></returns>
        public static string XmlMenuGenerator(DataTable tbl)
        {

            Type oType = tbl.Rows[0]["Id"].GetType();
            object oDefault = default(object);
            switch (oType.FullName)
            {
                case "System.Int32":
                    oDefault = default(Int32);
                    break;
                case "System.Guid":
                    oDefault = default(Guid);
                    break;
                default:
                    throw new Exception("Type were not found!");
            }


            StringBuilder sb = new StringBuilder(@"<?xml version='1.0' encoding='utf-8' ?><Home>");
            foreach (DataRow i in tbl.Select(string.Format("[Parent] = '{0}'",oDefault)))
            {
                string iTitle = i["Title"].ToString();
                string iUrl = i["Url"].ToString();
                string iId = i["Id"].ToString();
                tbl.Rows.Remove(i);
                sb.AppendFormat(@"<Menu text='{0}' url='{1}'>", iTitle, iUrl);
                XmlMenuGeneratorNested(tbl, sb, iId);
                sb.Append("</Menu>");
            }
            sb.Append("</Home>");
            return sb.ToString();
        }

        private static void XmlMenuGeneratorNested<T>(DataTable tbl,StringBuilder sb,T pId)
        {
            foreach (DataRow i in tbl.Select(string.Format("[Parent] = '{0}'", pId)))
            {
                string iTitle = i["Title"].ToString();
                string iUrl = i["Url"].ToString();
                string iId = i["Id"].ToString();
                tbl.Rows.Remove(i);
                sb.AppendFormat(@"<SubMenu text='{0}' url='{1}'>", iTitle, iUrl);
                XmlMenuGeneratorNested(tbl, sb, iId);
                sb.Append("</SubMenu>");
            }
        }

        public static string ConnectionString
        {
            get
            {
                if (string.IsNullOrEmpty(_connectionString))
                {
                    _connectionString = ConfigurationManager.ConnectionStrings[
                        ConfigurationManager.AppSettings["matrix_connection"]
                    ].ConnectionString;
                }
                return _connectionString;
            }

        }

        /// <summary>
        /// To convert array to parameter string
        /// Right now support string , int , Guid
        /// </summary>
        /// <typeparam name="T">Anytype</typeparam>
        /// <param name="cKey">Key parameters</param>
        /// <returns>Parameter string</returns>
        public static string CreateSeriesOfParameters<T>(T[] cKey)
        {
            StringBuilder sb = new StringBuilder();
            string format = string.Empty;

            if (cKey is Int32[])
            {
                format = "{0}";
            }
            else
            {
                format = "'{0}'";
            }

            for (int i = 0; i < cKey.Length; i++)
            {
                if (i == 0)
                {
                    sb.AppendFormat(format, cKey[i]);
                }
                else
                {
                    sb.AppendFormat(","+format, cKey[i]);
                }
            }
            return sb.ToString();
        }

        public static DataSet GetDataSet(string cmdText, params SqlParameter[] cKeyPaire)
        {
            DataSet ds = new DataSet();
            using (SqlDataAdapter adp = new SqlDataAdapter(cmdText, CodeHelper.ConnectionString))
            {
                foreach (SqlParameter i in cKeyPaire)
                {
                    adp.SelectCommand.Parameters.Add(i);
                }
                adp.Fill(ds);
            }
            return ds;
        }

        public static DataTable GetDataTable(string cmdText, params SqlParameter[] cKeyPaire)
        {
            DataTable tbl = new DataTable();
            using (SqlConnection c = new SqlConnection(CodeHelper.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand(cmdText, c);
                foreach (SqlParameter i in cKeyPaire)
                {
                    cmd.Parameters.Add(i);
                }
                if (c.State == ConnectionState.Open)
                {
                    c.Close();
                }
                c.Open();
                tbl.Load(cmd.ExecuteReader());
            }

            return tbl;
        }

        public static DataTable GetDataTable(string cmdText, CommandType cmdType, params SqlParameter[] cKeyPaire)
        {
            DataTable tbl = new DataTable();
            using (SqlConnection c = new SqlConnection(CodeHelper.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand(cmdText, c);
                cmd.CommandType = cmdType;
                foreach (SqlParameter i in cKeyPaire)
                {
                    cmd.Parameters.Add(i);
                }
                if (c.State == ConnectionState.Open)
                {
                    c.Close();
                }
                c.Open();
                tbl.Load(cmd.ExecuteReader());
            }

            return tbl;
        }

        public static object GetSingleObject(string cmdText, params SqlParameter[] cKeyPaire)
        {
            using (SqlConnection c = new SqlConnection(CodeHelper.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand(cmdText, c);
                foreach (SqlParameter i in cKeyPaire)
                {
                    cmd.Parameters.Add(i);
                }
                if (c.State == ConnectionState.Open)
                {
                    c.Close();
                }
                c.Open();
                return cmd.ExecuteScalar();
            }
        }

        public static DataRow GetDataRow(string cmdText, params SqlParameter[] cKeyPaire)
        {
            DataTable tbl = CodeHelper.GetDataTable(cmdText, cKeyPaire);
            if (tbl.Rows.Count == 0)
            {
                return null;
            }
            else
            {
                return tbl.Rows[0];
            }
        }

        public static DataRow GetDataRow(string cmdText, CommandType cmdType, params SqlParameter[] cKeyPaire)
        {
            DataTable tbl = CodeHelper.GetDataTable(cmdText, cmdType, cKeyPaire);
            if (tbl.Rows.Count == 0)
            {
                return null;
            }
            else
            {
                return tbl.Rows[0];
            }
        }

        public static int ExecuteNonQuery(string cmdText, params SqlParameter[] cKeyPaire)
        {
            int rs = 0;
            using (SqlConnection c = new SqlConnection(CodeHelper.ConnectionString))
            {
                SqlCommand cmd = new SqlCommand(cmdText, c);
                foreach (SqlParameter i in cKeyPaire)
                {
                    cmd.Parameters.Add(i);
                }
                if (c.State == ConnectionState.Open)
                {
                    c.Close();
                }
                c.Open();
                rs = cmd.ExecuteNonQuery();
            }

            return rs;
        }

        public static ListItemCollection ArrangeHirachy(DataTable srcTbl,string expfilterRoot,string keyId,string parentId,string displayText)
        {

            ListItemCollection cItem = new ListItemCollection();
            string filterRoot = string.Format("{0} ", expfilterRoot);
            foreach (DataRow i in srcTbl.Select(filterRoot))
            {
                ListItem iItem = new ListItem() {
                        Text = i[displayText].ToString(),
                        Value = i[keyId].ToString()
                    };
                cItem.Add(iItem);
                srcTbl.Rows.RemoveAt(srcTbl.Rows.IndexOf(i));
                ArrangeHirachyNested(
                    srcTbl,
                    cItem,
                    iItem,
                    keyId,
                    parentId,
                    displayText);
            }
            return cItem;
        }

        private static void ArrangeHirachyNested(DataTable srcTbl,ListItemCollection cItem,ListItem parentItem ,string keyId, string parentId, string displayText)
        {
            foreach (DataRow i in srcTbl.Select(string.Format("{0} = {1}",parentId,parentItem.Value)))
            {
                ListItem iItem = new ListItem()
                {
                    Text = i[displayText].ToString(),
                    Value = i[keyId].ToString()
                };
                cItem.Add(iItem);
                srcTbl.Rows.RemoveAt(srcTbl.Rows.IndexOf(i));
                ArrangeHirachyNested(
                    srcTbl,
                    cItem,
                    iItem,
                    keyId,
                    parentId,
                    displayText
                );
            }
        }



        public static DataTable ArrangeHirachy(DataTable srcTbl, string expfilterRoot, string keyColumnName, string parentColumnName)
        {

            DataTable cItem = srcTbl.Clone();
            string filterRoot = string.Format("{0} ", expfilterRoot);
            foreach (DataRow i in srcTbl.Select(filterRoot))
            {

                cItem.Rows.Add(i.ItemArray);
                
                ArrangeHirachyNested(
                    srcTbl,
                    cItem,
                    i,
                    keyColumnName,
                    parentColumnName
                    );
                srcTbl.Rows.RemoveAt(srcTbl.Rows.IndexOf(i));
            }
            return cItem;
        }


        private static void ArrangeHirachyNested(DataTable srcTbl, DataTable cItem, DataRow parentItem, string keyColumnName, string parentColumnName)
        {
            foreach (DataRow i in srcTbl.Select(string.Format("{0} = {1}", parentColumnName, parentItem[keyColumnName])))
            {

                cItem.Rows.Add(i.ItemArray);
                ArrangeHirachyNested(
                    srcTbl,
                    cItem,
                    i,
                    keyColumnName,
                    parentColumnName
                );
                srcTbl.Rows.RemoveAt(srcTbl.Rows.IndexOf(i));
            }
        }



    }


}




